package mrusanov.ui.battle

import mrusanov.team.Team
import mrusanov.battle.{MiniArena, Battle}

class BattleUIController(userTeam:Team, battlePanel:BattlePanel) {
  private val battle = battlePanel.battle
  private var selectedMiniArena:Option[MiniArena] = None

  def buttonClicked(arena:MiniArena) {
      if (selectedMiniArena.isEmpty) {
        selectedMiniArena = Some(arena)
      } else {
        assert(selectedMiniArena.isDefined, "MiniArena must be defined")
        val current = selectedMiniArena.get
        if (current.isOver) {
          val player = current.getPlayer(userTeam)
          assert(player.isDefined, "Player must not be null at this stage")
          if (arena.getPlayer(userTeam).isDefined) {
            battle.swapPlayers(player.get, arena.getPlayer(userTeam).get)
          } else {
            battle.moveVictoriousPlayerToNewArena(player.get, arena)
          }
          selectedMiniArena = None
        } else {
          val player = current.getPlayer(userTeam)
          assert(player.isDefined, "Impossible for player to be null, fight is not isOver")
          val swapped = arena.getPlayer(userTeam)
          assert(swapped.isDefined, "Impossible for player to be null, fight is not isOver")

          battle.swapPlayers(player.get, swapped.get)
          selectedMiniArena = None
        }
      }

    battlePanel.refresh()
  }

  def buildUnitOrderComponent(arena:MiniArena):UnitOrderComponentState = {
    selectedMiniArena match {
      case Some(selected) => buildUnitOrderComponentForSelectedArena(selected, arena)
      case None => buildUnitOrderComponentForNotSelectedArena(arena)
    }
  }

  private def buildUnitOrderComponentForSelectedArena(selected:MiniArena, current:MiniArena):UnitOrderComponentState = {
    if (shouldBuildCancelComponent(selected, current)) {
      return new CancelUnitButton(current, this)
    }

    if (shouldBuildEmptyComponent(selected, current)) {
      return new EmptyButton(current, this)
    }

    if (shouldBuildMoveComponent(selected, current)) {
      return new MoveUnitButton(selected, current, this)
    }

    if (shouldBuildSwapComponent(selected, current)) {
      return new SwapUnitButton(selected, current, this)
    }

    throw new RuntimeException("Unreachable code")
  }

  private def buildUnitOrderComponentForNotSelectedArena(current:MiniArena):UnitOrderComponentState = {
    if (shouldBuildEmptyComponent(current)) {
      return new EmptyButton(current, this)
    }

    if (shouldBuildSelectComponent(current)) {
      return new SelectUnitButton(current, this)
    }

    throw new RuntimeException("Unreachable code")
  }

  private def shouldBuildEmptyComponent(arena:MiniArena):Boolean = {
    // there is no player at all
    (arena.getPlayer(userTeam).isEmpty) ||
    // team swapped and player has not won
    (battle.swapped(userTeam) && !arena.isOver)
  }

  private def shouldBuildEmptyComponent(from:MiniArena, target:MiniArena):Boolean = {
    // there is player and enemy and already swap took place
    (from.getPlayer(userTeam).isDefined && !from.isOver && battle.swapped(userTeam)) ||
    // it is not possible to swap
    (!from.isOver && from.getPlayer(userTeam).isDefined && target.getPlayer(userTeam).isEmpty) ||
    // target duel is already isOver
    target.isOver || (from.isOver && target.getPlayer(userTeam).isDefined)

  }

  private def shouldBuildMoveComponent(from:MiniArena, target:MiniArena):Boolean = {
    // if current arena was won and this arena is not started
    from.isOver && from.getPlayer(userTeam).isDefined &&
    target.getPlayer(userTeam).isEmpty && !target.isStarted
  }

  private def shouldBuildSwapComponent(from:MiniArena, target:MiniArena):Boolean = {
    from.getPlayer(userTeam).isDefined && target.getPlayer(userTeam).isDefined &&
    !battle.swapped(userTeam)
  }

  private def shouldBuildCancelComponent(from:MiniArena, target:MiniArena):Boolean = {
    from == target
  }

  private def shouldBuildSelectComponent(arena:MiniArena):Boolean = {
     // when there was no swapping and player of user team is present in cell
     !battle.swapped(userTeam) && arena.getPlayer(userTeam).isDefined
  }

  def turnOver() {
    selectedMiniArena = None
  }
}
